package com.moter.estest.util;

import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.ingest.PutPipelineRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class ESUtils<T> {
    @Qualifier("restHighLevelClient")
    @Autowired
    private RestHighLevelClient client;

    /**
     * 判断索引是否存在
     *
     * @param index
     * @return
     * @throws IOException
     */
    public boolean existsIndex(String index) throws IOException {
        GetIndexRequest request = new GetIndexRequest(index);
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        return exists;
    }

    /**
     * 创建索引
     *
     * @param index
     * @return
     * @throws IOException
     */
    public boolean createIndex(String index) throws IOException {
        CreateIndexRequest request = new CreateIndexRequest(index);
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

    /**
     * 删除索引
     *
     * @param index
     * @return
     * @throws IOException
     */
    public boolean deleteIndex(String index) throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest(index);
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

    /**
     * 判断文档是否存在
     *
     * @param index 索引
     * @param id    文档id
     * @return
     * @throws IOException
     */
    public boolean docExits(String index, String id) throws IOException {
        GetRequest request = new GetRequest(index, id);
        //值判断索引是否存在不需要获取_source
        request.fetchSourceContext(new FetchSourceContext(false));
        request.storedFields("_none_");
        return client.exists(request, RequestOptions.DEFAULT);
    }

    /**
     * 添加文档
     *
     * @param index    索引
     * @param id       文档id
     * @param t        对象
     * @param pipeline 管道名称
     * @return
     * @throws IOException
     */
    public boolean addDoc(String index, String id, T t, String pipeline) throws IOException {
        IndexRequest request = new IndexRequest(index);
//        request.id(id);
        request.setPipeline(pipeline);
//        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        //对象转为json
        request.source(JSON.toJSONString(t), XContentType.JSON);
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        RestStatus status = response.status();
        return status == RestStatus.OK || status == RestStatus.CREATED;
    }

    /**
     * 根据id获取文档
     *
     * @param index 索引
     * @param id    id
     * @return
     * @throws IOException
     */
    public GetResponse getDoc(String index, String id) throws IOException {
        GetRequest request = new GetRequest(index, id);
        GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
        return getResponse;
    }

    /*** 批量添加文档记录 * 没有设置id ES会自动生成一个，如果要设置 IndexRequest的对象.id()即可 * @param index * @param list * @return * @throws IOException */
    public boolean bulkAdd(String index, List<T> list, String pipeline) throws IOException {

        BulkRequest bulkRequest = new BulkRequest();
        //timeout
//        bulkRequest.timeout(TimeValue.timeValueMinutes(2));
        bulkRequest.timeout("2m");
        bulkRequest.pipeline(pipeline);
        for (int i = 0; i < list.size(); i++) {
            bulkRequest.add(new IndexRequest(index).source(JSON.toJSONString(list.get(i)), XContentType.JSON));
        }
        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        return !bulkResponse.hasFailures();
    }

    public SearchResponse searchContentHighlight(String index, int pageNo, int pageSize, String keyword) throws IOException {
        // 创建查询请求
        SearchRequest searchRequest = new SearchRequest(index);
        // 创建查询参数
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);
        //精准匹配
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //设置四要素 处罚机构 发文案号 处罚时间 法律依据
        MatchPhraseQueryBuilder phraseQuery1 = QueryBuilders.matchPhraseQuery("attachment.content", "处罚机构");
        MatchPhraseQueryBuilder phraseQuery2 = QueryBuilders.matchPhraseQuery("attachment.content", "发文案号");
        MatchPhraseQueryBuilder phraseQuery3 = QueryBuilders.matchPhraseQuery("attachment.content", "处罚时间");
        MatchPhraseQueryBuilder phraseQuery4 = QueryBuilders.matchPhraseQuery("attachment.content", "法律依据");
        boolQueryBuilder.must(phraseQuery1);
        boolQueryBuilder.must(phraseQuery2);
        boolQueryBuilder.must(phraseQuery3);
        boolQueryBuilder.must(phraseQuery4);

        // 关键字查询
        MatchQueryBuilder matchQueryContent = QueryBuilders.matchQuery("title", keyword);
        MatchQueryBuilder matchQueryTitle = QueryBuilders.matchQuery("attachment.content", keyword);
        boolQueryBuilder.should(matchQueryContent);
        boolQueryBuilder.should(matchQueryTitle);


        // 查询条件结束
        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.fetchSource("title","attachment");
        //高亮设置
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //设置每个片段大小
        highlightBuilder.fragmentSize(200)
                //定义语言环境
                .boundaryScannerLocale("zh_CN")
                //设置片段按照段落格式
                .boundaryScannerType(HighlightBuilder.BoundaryScannerType.SENTENCE)
                //设置高亮字段
                .preTags("<span style='color:red;'>")
                .postTags("</span>")
                .field("attachment.content", 200, 3)
                .field("title", 20, 1);

        sourceBuilder.highlighter(highlightBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        //结束组装查询条件
        searchRequest.source(sourceBuilder);
        return client.search(searchRequest, RequestOptions.DEFAULT);
    }
}
